<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<title>composite 聚合 | ElasticSearch 7.7 权威指南中文版</title>
	<meta name="keywords" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <meta name="description" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
	<link rel="stylesheet" type="text/css" href="../static/styles.css" />
	<script>
	var _link = 'search-aggregations-bucket-composite-aggregation.html';
    </script>
</head>
<body>
<div class="main-container">
    <section id="content">
        <div class="content-wrapper">
            <section id="guide" lang="zh_cn">
                <div class="container">
                    <div class="row">
                        <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                            <div style="color:gray; word-break: break-all; font-size:12px;">原英文版地址: <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.7/search-aggregations-bucket-composite-aggregation.html" rel="nofollow" target="_blank">https://www.elastic.co/guide/en/elasticsearch/reference/7.7/search-aggregations-bucket-composite-aggregation.html</a>, 原文档版权归 www.elastic.co 所有<br/>本地英文版地址: <a href="../en/search-aggregations-bucket-composite-aggregation.html" rel="nofollow" target="_blank">../en/search-aggregations-bucket-composite-aggregation.html</a></div>
                        <!-- start body -->
                  <div class="page_header">
<strong>重要</strong>: 此版本不会发布额外的bug修复或文档更新。最新信息请参考 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html" rel="nofollow">当前版本文档</a>。
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch 权威指南 [7.7]</a></span>
»
<span class="breadcrumb-link"><a href="search-aggregations.html">聚合</a></span>
»
<span class="breadcrumb-link"><a href="search-aggregations-bucket.html">桶(bucket)聚合</a></span>
»
<span class="breadcrumb-node">composite 聚合</span>
</div>
<div class="navheader">
<span class="prev">
<a href="search-aggregations-bucket-children-aggregation.html">« children 聚合</a>
</span>
<span class="next">
<a href="search-aggregations-bucket-datehistogram-aggregation.html">date_histogram 聚合 »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="search-aggregations-bucket-composite-aggregation"></a>复合(composite)聚合
</h2>
</div></div></div>
<p>一个多桶(multi-bucket)聚合，从不同来源创建复合桶。</p>
<p>
与其他<code class="literal">多桶(multi-bucket)</code>聚合不同，<code class="literal">composite</code> 聚合可用于高效地对多级聚合中的<span class="strong strong"><strong>所有</strong></span>桶进行分页。

这种聚合提供了一种方法，类似于 <a class="xref" href="search-request-body.html#request-body-search-scroll" title="scroll" rel="nofollow">scroll</a> 对文档所做的那样，对特定聚合的所有桶进行流式处理。
</p>
<p>复合桶是从为每个文档提取/创建的值的组合中构建的，并且每个组合被认为是一个复合桶。</p>
<p>比如下面的文档：</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">{
    "keyword": ["foo", "bar"],
    "number": [23, 65, 76]
}</pre>
</div>
<p>
... 当<code class="literal">keyword</code> 和 <code class="literal">number</code>用作聚合的值的来源时，创建以下复合桶：
</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">{ "keyword": "foo", "number": 23 }
{ "keyword": "foo", "number": 65 }
{ "keyword": "foo", "number": 76 }
{ "keyword": "bar", "number": 23 }
{ "keyword": "bar", "number": 65 }
{ "keyword": "bar", "number": 76 }</pre>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_values_source_2"></a>值的来源<span class="remark">(value source)</span>
</h3>
</div></div></div>
<p>
参数 <code class="literal">sources</code> 控制应该用于构建复合桶的源。

定义 <code class="literal">sources</code> 的顺序很重要，因为它也控制着 key 的返回顺序。
</p>
<p>每个源的名称必须是唯一的。</p>
<p>值的来源有三种不同类型：</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="_terms"></a>terms <span class="remark">（词项）</span>
</h4>
</div></div></div>
<p>
<code class="literal">terms</code> 值来源相当于一个简单的 <code class="literal">terms</code> 集合。

这些值是从字段或脚本中提取的，就像 <code class="literal">terms</code> 聚合一样。
</p>
<p>例如：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    { "product": { "terms" : { "field": "product" } } }
                ]
            }
        }
     }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/423.console"></div>
<p>与 <code class="literal">terms</code> 聚合一样，也可以使用脚本来创建复合桶的值：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    {
                        "product": {
                            "terms" : {
                                "script" : {
                                    "source": "doc['product'].value",
                                    "lang": "painless"
                                }
                            }
                        }
                    }
                ]
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/424.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="_histogram"></a>histogram <span class="remark">（直方图）</span>
</h4>
</div></div></div>
<p>
<code class="literal">histogram</code> 值来源可应用于数值，以在这些值上构建固定大小的间隔。

参数 <code class="literal">interval</code> 定义应该如何转换数值。

例如， <code class="literal">interval</code> 设置为 5 会将任何数值转换为最接近 5 的间隔，值 <code class="literal">101</code> 会转换为 <code class="literal">100</code>，因为 101 在间隔 100 和 105 之间。
</p>
<p>例如：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    { "histo": { "histogram" : { "field": "price", "interval": 5 } } }
                ]
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/425.console"></div>
<p>这些值由 numeric(数值)字段或返回数值的脚本构建而成：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    {
                        "histo": {
                            "histogram" : {
                                "interval": 5,
                                "script" : {
                                    "source": "doc['price'].value",
                                    "lang": "painless"
                                }
                            }
                        }
                    }
                ]
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/426.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="_date_histogram"></a>date histogram <span class="remark">(日期直方图)</span>
</h4>
</div></div></div>
<p><code class="literal">date_histogram</code>值源类似于 <code class="literal">histogram</code>，只是它的时间间隔是由日期/时间表达式指定的：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    { "date": { "date_histogram" : { "field": "timestamp", "calendar_interval": "1d" } } }
                ]
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/427.console"></div>
<p>
上面的示例创建了一个每天的时间间隔，并将所有 <code class="literal">timestamp</code> 值转换为最接近的时间间隔的开始。

间隔的可用表达式有：<code class="literal">year</code>、<code class="literal">quarter</code>, <code class="literal">month</code>、<code class="literal">week</code>、<code class="literal">day</code>、<code class="literal">hour</code>、<code class="literal">minute</code>、<code class="literal">second</code>。
</p>
<p>
时间值也可以通过<a class="xref" href="common-options.html#time-units" title="Time units" rel="nofollow">时间单位(time units)</a>解析支持的缩写来指定。

请注意，不支持带小数点的时间值，但是你可以通过转换到另一个时间单位来解决这个问题(例如，可以将<code class="literal">1.5h</code>指定为<code class="literal">90m</code>)。
</p>
<p>&nbsp;</p>
<p><span class="strong strong"><strong>format</strong></span></p>
<p>
在内部，一个日期被表示为一个64位的数字-一个时间戳，以毫秒为单位。 

这些时间戳作为桶的 key 返回。

可以使用参数<code class="literal">format</code>指定的格式返回格式化的日期字符串：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    {
                        "date": {
                            "date_histogram" : {
                                "field": "timestamp",
                                "calendar_interval": "1d",
                                "format": "yyyy-MM-dd" <a id="CO215-1"></a><i class="conum" data-value="1"></i>
                            }
                        }
                    }
                ]
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/428.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO215-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>支持<a class="xref" href="search-aggregations-bucket-daterange-aggregation.html#date-format-pattern" title="date 格式/模式" rel="nofollow">日期格式/模式</a>表达式</p>
</td>
</tr>
</table>
</div>
<p><span class="strong strong"><strong>时区</strong></span></p>
<p>
日期时间以 UTC 存储在 Elasticsearch 中。

默认情况下，所有的分桶和舍入也在 UTC 中完成。

<code class="literal">time_zone</code> 参数可用于指示分桶时应该使用不同的时区。
</p>
<p>
时区可以指定为 ISO 8601 UTC 时差(例如<code class="literal">+01:00</code> 或 <code class="literal">-08:00</code>)，也可以指定为时区id(在TZ数据库中使用的标识符)，比如<code class="literal">America/Los_Angeles</code>。
</p>
<p><span class="strong strong"><strong>Offset</strong></span></p>
<p>
使用 <code class="literal">offset</code> 参数按指定的正(<code class="literal">+</code>)或负(<code class="literal">-</code>)偏移量持续时间来更改每个桶的起始值，例如<code class="literal">1h</code>表示一个小时，<code class="literal">1d</code>表示一天。

有关更多可能的持续时间选项，请参见<a class="xref" href="common-options.html#time-units" title="时间单位" rel="nofollow">时间单位(time units)</a>。
</p>
<p>
例如，当使用<code class="literal">day</code>作为时间间隔时，每个桶的时间区间从午夜到午夜。

将参数 <code class="literal">offset</code> 设置为 <code class="literal">+6h</code> 会将每个桶的时间区间更改为从早上6点到早上6点：
</p>
<a id="composite-aggregation-datehistogram-offset-example"></a><div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">
#添加并索引两个文档
PUT my_index/_doc/1?refresh
{
  "date": "2015-10-01T05:30:00Z"
}

PUT my_index/_doc/2?refresh
{
  "date": "2015-10-01T06:30:00Z"
}

#搜索
GET my_index/_search?size=0
{
  "aggs": {
    "my_buckets": {
      "composite" : {
        "sources" : [
          {
            "date": {
              "date_histogram" : {
                "field": "date",
                "calendar_interval": "day",
                "offset": "+6h",
                "format": "iso8601"
              }
            }
          }
        ]
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/429.console"></div>
<p>上面的请求的单个桶不是从午夜开始，而是从早上6点开始：</p>
<div class="pre_wrapper lang-console-result">
<pre class="programlisting prettyprint lang-console-result">{
  ...
  "aggregations": {
    "my_buckets": {
      "after_key": { "date": "2015-10-01T06:00:00.000Z" },
      "buckets": [
        {
          "key": { "date": "2015-09-30T06:00:00.000Z" },
          "doc_count": 1
        },
        {
          "key": { "date": "2015-10-01T06:00:00.000Z" },
          "doc_count": 1
        }
      ]
    }
  }
}</pre>
</div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>在进行 <code class="literal">time_zone</code> 调整后，计算每个桶的起始 <code class="literal">offset</code> 值。</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h4 class="title">
<a id="_mixing_different_values_source"></a>混合不同的值源
</h4>
</div></div></div>
<p>
参数 <code class="literal">sources</code> 接受一个值源数组。可以混合不同的值源来创建复合桶。例如：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    { "date": { "date_histogram": { "field": "timestamp", "calendar_interval": "1d" } } },
                    { "product": { "terms": {"field": "product" } } }
                ]
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/430.console"></div>
<p>
这将从由两个值源创建的值创建复合桶，一个<code class="literal">date_histogram</code>和一个<code class="literal">terms</code>。

每个桶由两个值组成，聚合中定义的每个值源对应一个值。

允许任何类型的组合，并且在组合桶中保留数组中的顺序。
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    { "shop": { "terms": {"field": "shop" } } },
                    { "product": { "terms": { "field": "product" } } },
                    { "date": { "date_histogram": { "field": "timestamp", "calendar_interval": "1d" } } }
                ]
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/431.console"></div>
</div>

</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_order"></a>排序 (order)
</h3>
</div></div></div>
<p>
默认情况下，复合桶按其自然顺序排序。

值按其值的升序排序。

当请求多个值源时，将对每个值源进行排序，将组合桶的第一个值与另一个组合桶的第一个值进行比较，如果它们相等，则组合桶中的下一个值将用于再次比较。

这意味着复合桶 <code class="literal">[foo, 100]</code>被认为比 <code class="literal">[foobar, 0]</code> 小，因为 <code class="literal">foo</code> 被认为比 <code class="literal">foobar</code> 小。

通过直接在值源定义中将 <code class="literal">order</code> 设置为<code class="literal">asc</code>(升序，默认值)或<code class="literal">desc</code>(降序)，可以定义每个值源的排序方向。例如:
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    { "date": { "date_histogram": { "field": "timestamp", "calendar_interval": "1d", "order": "desc" } } },
                    { "product": { "terms": {"field": "product", "order": "asc" } } }
                ]
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/432.console"></div>
<p>当比较 <code class="literal">date_histogram</code> 源中的值时，将按降序对复合桶进行排序，当比较 <code class="literal">terms</code> 源中的值时，将按升序对复合桶进行排序。</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_missing_bucket"></a>缺失的桶
</h3>
</div></div></div>
<p>
默认情况下，没有给定来源值的文档将被忽略。

通过将 <code class="literal">missing_bucket</code> 设置为 <code class="literal">true</code> (默认为 <code class="literal">false</code>)，可以将它们包含在响应中:
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    { "product_name": { "terms" : { "field": "product", "missing_bucket": true } } }
                ]
            }
        }
     }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/433.console"></div>
<p>
在上面的示例中，对于字段 <code class="literal">product</code> 没有值的文档，源 <code class="literal">product_name</code> 将生成一个显式的 <code class="literal">null</code> 值。 

源中指定的 <code class="literal">order</code> 决定了 <code class="literal">null</code> 应该排在第一位(升序，<code class="literal">asc</code>)还是最后一位(降序，<code class="literal">desc</code>)。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_size_2"></a>size
</h3>
</div></div></div>
<p>
可以设置参数 <code class="literal">size</code> 来定义应该返回多少个复合桶。

每个组合桶都被视为一个桶，因此将大小设置为 10 将返回从值源创建的前 10 个组合桶。

响应的数组中包含每个组合桶的值，该数组包含从每个值源提取的值。
</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_pagination"></a>分页(pagination)
</h3>
</div></div></div>
<p>
如果复合桶的数量太多(或未知)而无法在单个响应中返回，则可以将检索分成多个请求。

因为复合桶本质上是扁平的，所以请求的 <code class="literal">size</code> 正好是响应中返回的复合桶的数量(假设它们至少是要返回的 <code class="literal">size</code> 个复合桶)。

如果应该检索所有的组合桶，最好使用一个较小的 <code class="literal">size</code> 值(例如 <code class="literal">100</code> 或 <code class="literal">1000</code> )，然后使用参数 <code class="literal">after</code> 检索下一个结果。例如:
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "size": 2,
                "sources" : [
                    { "date": { "date_histogram": { "field": "timestamp", "calendar_interval": "1d" } } },
                    { "product": { "terms": {"field": "product" } } }
                ]
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/434.console"></div>
<p>... 返回：</p>
<div class="pre_wrapper lang-console-result">
<pre class="programlisting prettyprint lang-console-result">{
    ...
    "aggregations": {
        "my_buckets": {
            "after_key": {
                "date": 1494288000000,
                "product": "mad max"
            },
            "buckets": [
                {
                    "key": {
                        "date": 1494201600000,
                        "product": "rocky"
                    },
                    "doc_count": 1
                },
                {
                    "key": {
                        "date": 1494288000000,
                        "product": "mad max"
                    },
                    "doc_count": 2
                }
            ]
        }
    }
}</pre>
</div>
<p>
要获得下一组桶，请重新发送相同的聚合，将参数 <code class="literal">after</code> 设置为响应中返回的 <code class="literal">after_key</code> 的值。

例如，下面的请求使用在之前的响应中提供的 <code class="literal">after_key</code> 的值:
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "size": 2,
                 "sources" : [
                    { "date": { "date_histogram": { "field": "timestamp", "calendar_interval": "1d", "order": "desc" } } },
                    { "product": { "terms": {"field": "product", "order": "asc" } } }
                ],
                "after": { "date": 1494288000000, "product": "mad max" } <a id="CO216-1"></a><i class="conum" data-value="1"></i>
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/435.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO216-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>应该将聚合限制为在提供的值的排序<span class="strong strong"><strong>之后(after)</strong></span>的桶。</p>
</td>
</tr>
</table>
</div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>
<code class="literal">after_key</code> <span class="strong strong"><strong>通常</strong></span>是响应中返回的最后一个桶的key，但这并不能保证。

总是使用返回的 <code class="literal">after_key</code>，而不是从桶中取出它。
</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_early_termination"></a>提前终止 (early termination)
</h3>
</div></div></div>
<p>
为了获得最佳性能，应该对索引设置<a class="xref" href="index-modules-index-sorting.html" title="Index Sorting" rel="nofollow">索引排序(index sort)</a>，以便它匹配复合聚合中的部分或全部源顺序。

例如下面的索引排序：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT twitter
{
    "settings" : {
        "index" : {
            "sort.field" : ["username", "timestamp"],   <a id="CO217-1"></a><i class="conum" data-value="1"></i>
            "sort.order" : ["asc", "desc"]              <a id="CO217-2"></a><i class="conum" data-value="2"></i>
        }
    },
    "mappings": {
        "properties": {
            "username": {
                "type": "keyword",
                "doc_values": true
            },
            "timestamp": {
                "type": "date"
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/436.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO217-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>该索引首先按 <code class="literal">username</code> 排序，然后按<code class="literal">timestamp</code>排序。</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO217-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p>…​ <code class="literal">username</code> 字段按升序排列，<code class="literal">timestamp</code> 字段按降序排列。</p>
<div class="olist orderedlist">
<ol class="orderedlist">
<li class="listitem">
可用于优化这些复合聚合：
</li>
</ol>
</div>
</td>
</tr>
</table>
</div>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    { "user_name": { "terms" : { "field": "user_name" } } }     <a id="CO218-1"></a><i class="conum" data-value="1"></i>
                ]
            }
        }
     }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/437.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO218-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">user_name</code> 是索引排序和顺序匹配(<code class="literal">asc</code>)的前缀。</p>
</td>
</tr>
</table>
</div>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    { "user_name": { "terms" : { "field": "user_name" } } }, <a id="CO219-1"></a><i class="conum" data-value="1"></i>
                    { "date": { "date_histogram": { "field": "timestamp", "calendar_interval": "1d", "order": "desc" } } } <a id="CO219-2"></a><i class="conum" data-value="2"></i>
                ]
            }
        }
     }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/438.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO219-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">user_name</code> 是索引排序和顺序匹配(<code class="literal">asc</code>)的前缀。</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO219-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">timestamp</code> 也匹配前缀，并且顺序匹配(<code class="literal">desc</code>)。</p>
</td>
</tr>
</table>
</div>
<p>
为了对提前终止(early termination)进行优化，建议将请求中的 <code class="literal">track_total_hits</code> 设置为<code class="literal">false</code>。

匹配请求的总命中数可以在第一次请求时检索，在每一页上计算这个数值的成本是很高的：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "track_total_hits": false,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                "sources" : [
                    { "user_name": { "terms" : { "field": "user_name" } } },
                    { "date": { "date_histogram": { "field": "timestamp", "calendar_interval": "1d", "order": "desc" } } }
                ]
            }
        }
     }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/439.console"></div>
<p>
请注意，源的顺序很重要，在下面的示例中，用 <code class="literal">timestamp</code> 调换 <code class="literal">user_name</code> 将会禁用排序优化，因为这种配置与索引排序的规范不匹配。

如果源的顺序对你的用例不重要，可以遵循这些简单的准则：
</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
将基数最高的字段放在第一位。<span class="remark">(这个与MySQL的优化类似)</span>
</li>
<li class="listitem">
确保字段的顺序与索引排序的顺序相匹配。
</li>
<li class="listitem">
将多值字段放在最后，因为它们不能用于提前终止。
</li>
</ul>
</div>
<div class="warning admon">
<div class="icon"></div>
<div class="admon_content">
<p>
<a class="xref" href="index-modules-index-sorting.html" title="Index Sorting" rel="nofollow">索引排序(index sort)</a> 会降低索引编排的速度，使用你的特定用例和数据集测试索引排序以确保它符合你的要求是非常重要的。

即使你没有注意到这一点，<code class="literal">composite</code> 聚合也会尝试在查询匹配所有文档(<code class="literal">match_all</code>查询)的情况下提前终止非排序索引。 
</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_sub_aggregations"></a>子聚合
</h3>
</div></div></div>
<p>
与任何 <code class="literal">multi-bucket</code>(多桶) 聚合一样，<code class="literal">composite</code> 聚合可以包含子聚合。

这些子聚合可用于计算其他桶或由此父聚合创建的每个复合桶的统计数据。

例如，下面的示例计算每个复合桶的 price 字段的平均值:
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET /_search
{
    "size": 0,
    "aggs" : {
        "my_buckets": {
            "composite" : {
                 "sources" : [
                    { "date": { "date_histogram": { "field": "timestamp", "calendar_interval": "1d", "order": "desc" } } },
                    { "product": { "terms": {"field": "product" } } }
                ]
            },
            "aggregations": {
                "the_avg": {
                    "avg": { "field": "price" }
                }
            }
        }
    }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/440.console"></div>
<p>... 返回：</p>
<div class="pre_wrapper lang-console-result">
<pre class="programlisting prettyprint lang-console-result">{
    ...
    "aggregations": {
        "my_buckets": {
            "after_key": {
                "date": 1494201600000,
                "product": "rocky"
            },
            "buckets": [
                {
                    "key": {
                        "date": 1494460800000,
                        "product": "apocalypse now"
                    },
                    "doc_count": 1,
                    "the_avg": {
                        "value": 10.0
                    }
                },
                {
                    "key": {
                        "date": 1494374400000,
                        "product": "mad max"
                    },
                    "doc_count": 1,
                    "the_avg": {
                        "value": 27.0
                    }
                },
                {
                    "key": {
                        "date": 1494288000000,
                        "product" : "mad max"
                    },
                    "doc_count": 2,
                    "the_avg": {
                        "value": 22.5
                    }
                },
                {
                    "key": {
                        "date": 1494201600000,
                        "product": "rocky"
                    },
                    "doc_count": 1,
                    "the_avg": {
                        "value": 10.0
                    }
                }
            ]
        }
    }
}</pre>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_pipeline_aggregations"></a>管道聚合(pipeline aggregations)
</h3>
</div></div></div>
<p>
目前复合聚合与管道聚合不兼容，在大多数情况下也没有意义。

例如，由于复合聚合的分页特性，单个逻辑分区(例如一天)可能会分布在多个页面上。

由于管道聚合纯粹是对最终桶列表的后处理，在复合页面上运行类似派生的东西可能会导致不准确的结果，因为它只考虑该页面上的“部分”结果。 
</p>
<p>将来可能会支持自包含到单个桶(如<code class="literal">bucket_selector</code>)的管道聚合。</p>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="search-aggregations-bucket-children-aggregation.html">« children 聚合</a>
</span>
<span class="next">
<a href="search-aggregations-bucket-datehistogram-aggregation.html">date_histogram 聚合 »</a>
</span>
</div>
</div>

                  <!-- end body -->
                        </div>
                        <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                        
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </section>
</div>
<script src="../static/cn.js"></script>
</body>
</html>